package com.jsecode.protocol.gid22;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.ByteBuf;


/**
 * 车辆定时上报GPS定位数据 0x00
 *
 *
 * @author grind
 * @date Mar 31, 2014 1:50:26 PM
 * @version 1.0
 */
public class GidGps extends GidBody {
    protected static Logger logger = LoggerFactory.getLogger("gid22-GidGps");

    private static final int TEN_POWER6 = 1000000;

    private Date time; // 6 个字节， 具体定义见下面
                            //    0   GPS Hour    1   u8  0 to 23
                            //    1   GPS Minute  1   u8  0 to 59
                            //    2   GPS Seconds 1   u8  0 to 59
                            //    3   GPS Year    1   u8  0 to 99
                            //    4   GPS Month   1   u8  1 to 12
                            //    5   GPS Day 1   u8  1 to 31
    private double latitude; // 6   Latitude    4   u32 0.000001 degree units  Bit31=0/1  北纬/南纬
    private double longitude; // 10  Longitude   4   u32 0.000001 degree units  Bit31=0/1  东经/西经
    private int altitude; // 14  Altitude    3   u8  Meters
    private float speed; // 17  Speed   2   u16 单位 0.1 km/h
    private float direction; // 19  Direction   2   u16 单位0.1 degree units
    private int satellites; // 21  Satellites  1   u8  定位卫星数
    private int outStatus; // 22  Output Status   1   u8  Output
    private int accStatus; // 23  Input Status    1   u8  ACC状态
    private float vehBattery; // 24  Vehicle Battery 2   u16 汽车电瓶电压,单位0.1V
    
    private byte warn1;     //    BIT0  碰撞报警
                //    BIT1  拖车报警
                //    BIT2  翻车报警
                //    BIT3  低电压报警（汽车）
                //    BIT4  碰撞测试报警
                //          新增加速度超过1G小于4G上报，
                //          用以监控车辆加速度情况。
    private byte warn2; 
                //    BIT0  汽车点火上报
                //    BIT1  汽车熄火上报
                //    BIT2  车机拔出报警(带电池情况下)
                //    BIT3  车机插上报警(带电池情况下)
                //    BIT4  定位过长报警
                //    BIT5  怠速过长上报
    private byte warn3; 
                //    BIT0  GID FLASH故障报警
                //    BIT1  GID CAN模块故障报警
                //    BIT2  GID 3D传感器故障报警
                //    BIT3  GID GPS模块故障报警
    private byte[] attach; // 数据， 可能没有， 可能为2, 也可能为6
    
    // 非协议数据
    private Date recvData; // 记录接受到该数据包的时间, 非协议中包含数据
    private boolean isWarnData = false;

    public GidGps(int len){
        super(len);
    }
    
    public GidGps(int len, boolean isWarnData){
        super(len);
        this.isWarnData = isWarnData;
    }
    
    @Override
    public int unpack(ByteBuf srcBuf){
        // 如果数据包26, 29（+3个报警字段） 35(碰撞报警) 31为错误的后面加电压的包
        // 老的数据长度： 38 41(报警数据3个字节) 47(6个字节的碰撞报警)
        // 新的包（多加了2个自己的电压） 40 43  49  (45是由于43长度的数据包后面多加了电压的原因)
        // 怠速报警是 43 + 2 （注意区别碰撞报警的数据包 43+6）

        time = GidUtil.readDate6(srcBuf);
        long n = srcBuf.readUnsignedInt();
        // System.out.println(n);
        latitude = ((double)(n&0x7fffffff)) / TEN_POWER6;
        if ((n & (0x1<<31)) > 0) {
            latitude = -latitude;
        }
        n = srcBuf.readUnsignedInt();
        // System.out.println(n);
        longitude = ((double)(n&0x7fffffff)) / TEN_POWER6;
        if ((n & (0x1<<31)) > 0) {
            longitude = -longitude;
        }
        altitude = srcBuf.readUnsignedMedium();
        speed = srcBuf.readUnsignedShort() / 10f;
        direction = srcBuf.readUnsignedShort() / 10f;
        satellites = srcBuf.readUnsignedByte();
        outStatus = srcBuf.readUnsignedByte();
        // 2014.8.11 由于协议中高4位用于其他目地, 所以只取bit0
        accStatus = srcBuf.readUnsignedByte() & 0x01;
        // TODO: 规则定义
        // 由于报警数据大小为 3, 5, 9, 对于非报警数据, 判断len大于26就可以了
//        if (len == 26 || len == 29 || len == 35 || len == 31) {
//            vehBattery = srcBuf.readUnsignedShort()/10f;
//        }
        if ( isWarnData) {
            if (len == 29 || len == 35 || len == 31) {
                vehBattery = srcBuf.readUnsignedShort()/10f;
            }
        } else { // 正常gps数据
            if (len >= 26) {
                vehBattery = srcBuf.readUnsignedShort()/10f;
            }
            // TODO: 车机两个调试数据, 目前不处理, 这个在报警数据里面没有. 2015.7.20日协议修改引起的调整
            // Test flag1   4   u32 车机调试数据1
            // Test flag2  4   u32 车机调试数据2
        }

        recvData = new Date();
        
        if (isWarnData && srcBuf.readableBytes() >= 3) {
            warn1 = srcBuf.readByte();
            warn2 = srcBuf.readByte();
            warn3 = srcBuf.readByte();
            if (srcBuf.readableBytes() > 0) {
                attach = new byte[srcBuf.readableBytes()];
                srcBuf.readBytes(attach);
            }
        }
        return 0;
    }

    public Date getTime(){
        return time;
    }

    public void setTime(Date time){
        this.time = time;
    }

    public double getLatitude(){
        return latitude;
    }

    public void setLatitude(double latitude){
        this.latitude = latitude;
    }

    public double getLongitude(){
        return longitude;
    }

    public void setLongitude(double longitude){
        this.longitude = longitude;
    }

    public int getAltitude(){
        return altitude;
    }

    public void setAltitude(int altitude){
        this.altitude = altitude;
    }

    public float getSpeed(){
        return speed;
    }

    public void setSpeed(float speed){
        this.speed = speed;
    }

    public float getDirection(){
        return direction;
    }

    public void setDirection(float direction){
        this.direction = direction;
    }

    public int getSatellites(){
        return satellites;
    }

    public void setSatellites(int satellites){
        this.satellites = satellites;
    }

    public int getOutStatus(){
        return outStatus;
    }

    public void setOutStatus(int outStatus){
        this.outStatus = outStatus;
    }

    public int getAccStatus(){
        return accStatus;
    }

    public void setAccStatus(int accStatus){
        this.accStatus = accStatus;
    }

    public float getVehBattery(){
        return vehBattery;
    }

    public void setVehBattery(float vehBattery){
        this.vehBattery = vehBattery;
    }

    public byte getWarn1(){
        return warn1;
    }

    public void setWarn1(byte warn1){
        this.warn1 = warn1;
    }

    public byte getWarn2(){
        return warn2;
    }

    public void setWarn2(byte warn2){
        this.warn2 = warn2;
    }

    public byte getWarn3(){
        return warn3;
    }

    public void setWarn3(byte warn3){
        this.warn3 = warn3;
    }

    public byte[] getAttach(){
        return attach;
    }

    public void setAttach(byte[] attach){
        this.attach = attach;
    }

    public Date getRecvData(){
        return recvData;
    }

    public void setRecvData(Date recvData){
        this.recvData = recvData;
    }

    public boolean isWarnData(){
        return isWarnData;
    }

    public void setWarnData(boolean isWarnData){
        this.isWarnData = isWarnData;
    }


    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("time=").append(time).append(","); 
        sb.append("latitude=").append(latitude).append(","); 
        sb.append("longitude=").append(longitude).append(","); 
        sb.append("altitude=").append(altitude).append(","); 
        sb.append("speed=").append(speed).append(","); 
        sb.append("direction=").append(direction).append(","); 
        sb.append("satellites=").append(satellites).append(","); 
        sb.append("outStatus=").append(outStatus).append(","); 
        sb.append("accStatus=").append(accStatus).append(","); 
        sb.append("vehBattery=").append(vehBattery).append(","); 
        sb.append("warn1=").append(warn1).append(","); 
        sb.append("warn2=").append(warn2).append(","); 
        sb.append("warn3=").append(warn3).append(","); 
        sb.append("attach=").append(attach);
        return sb.toString();
    }


}
